home *** CD-ROM | disk | FTP | other *** search
/ Meeting Pearls 2 / Meeting Pearls Vol. II (1995)(GTI - Schatztruhe)[!].iso / Pearls / dev / GUI / BGUI / ARexxClass / ARexxClass.c < prev    next >
C/C++ Source or Header  |  1994-08-25  |  36KB  |  985 lines

  1. /*
  2. **         $RCSfile$
  3. **      Description: BOOPSI ARexx interface class.
  4. **        Copyright: (C) Copyright 1994 Jaba Development.
  5. **                   (C) Copyright 1994 Jan van den Baard.
  6. **                   All Rights Reserved.
  7. **
  8. **          $Author$
  9. **        $Revision$
  10. **            $Date$
  11. **/
  12.  
  13. /*
  14. **      Uncomment the following line if you want the
  15. **      class to use memory pools and you have got
  16. **      the 3.1 amiga.lib.
  17. **/
  18.  
  19. /* #define POOLS */
  20.  
  21. #ifdef POOLS
  22. #define AllocMemory(s)          GetMem( ad, s )
  23. #define FreeMemory(p)           PutMem( ad, p )
  24. #else
  25. #define AllocMemory(s)          AllocVec( s, MEMF_PUBLIC | MEMF_CLEAR )
  26. #define FreeMemory(p)           FreeVec( p )
  27. #endif
  28.  
  29. #include "ARexxClass.h"
  30.  
  31. #include <proto/intuition.h>
  32. #include <proto/utility.h>
  33. #include <proto/rexxsyslib.h>
  34. #include <proto/exec.h>
  35. #include <proto/dos.h>
  36.  
  37. #include <clib/alib_protos.h>
  38.  
  39. #include <stdio.h>
  40. #include <string.h>
  41. #include <ctype.h>
  42.  
  43. /*
  44. **      Compiler crap. Should compile under SAS this way...
  45. **/
  46. #ifdef _DCC
  47. #define SAVEDS __geta4
  48. #define ASM
  49. #define REG(x) __ ## x
  50. #else
  51. #define SAVEDS __saveds
  52. #define ASM __asm
  53. #define REG(x) register __ ## x
  54. #endif
  55.  
  56. /*
  57. **      Object instance data.
  58. **/
  59. typedef struct {
  60.         struct MsgPort                  *ad_Port;       /* Host message port. */
  61.         UBYTE                           *ad_HostName;   /* Host name. */
  62.         UBYTE                           *ad_FileExt;    /* File extention. */
  63.         ULONG                            ad_PendCnt;    /* Messages still un-reply'd. */
  64.         REXXCOMMAND                     *ad_Commands;   /* Host command list. */
  65.         struct RDArgs                   *ad_DOSParser;  /* ReadArgs() parser. */
  66.         UWORD                            ad_Flags;      /* See below. */
  67. #ifdef POOLS
  68.         APTR                             ad_MemPool;    /* Memory pool. */
  69. #endif
  70. } AD;
  71.  
  72. /*
  73. **      Module prototypes.
  74. **/
  75. STATIC ULONG SAVEDS ASM ARexxDispatch( REG(A0) Class *cl, REG(A2) Object *obj, REG(A1) Msg );
  76.  
  77. /*
  78. **      Class initialization.
  79. **/
  80. Class *InitARexxClass( void )
  81. {
  82.         Class                   *cl;
  83.  
  84.         if ( cl = MakeClass( NULL, ROOTCLASS, NULL, sizeof( AD ), 0L ))
  85.                 cl->cl_Dispatcher.h_Entry = (HOOKFUNC)ARexxDispatch;
  86.  
  87.         return( cl );
  88. }
  89.  
  90. /*
  91. **      Free the class.
  92. **/
  93. BOOL FreeARexxClass( Class *cl )
  94. {
  95.         return( FreeClass( cl ));
  96. }
  97.  
  98. #ifdef POOLS
  99. /*
  100. **      Pool allocation.
  101. **/
  102. STATIC APTR GetMem( AD *ad, ULONG size )
  103. {
  104.         ULONG                   *ptr;
  105.  
  106.         /*
  107.         **      Allocate the memory.
  108.         **/
  109.         if ( ptr = LibAllocPooled( ad->ad_MemPool, size + sizeof( ULONG ))) {
  110.                 /*
  111.                 **      Store allocation size.
  112.                 **/
  113.                 *ptr = size + sizeof( ULONG );
  114.                 /*
  115.                 **      Adjust pointer.
  116.                 **/
  117.                 ptr++;
  118.         }
  119.         return(( APTR )ptr );
  120. }
  121.  
  122. /*
  123. **      Pool freeing.
  124. **/
  125. STATIC VOID PutMem( AD *ad, APTR mem )
  126. {
  127.         ULONG                   *ptr = ( ULONG * )mem;
  128.  
  129.         /*
  130.         **      Retrieve the original allocation.
  131.         **/
  132.         ptr--;
  133.  
  134.         /*
  135.         **      Deallocate.
  136.         **/
  137.         LibFreePooled( ad->ad_MemPool, ptr, *ptr );
  138. }
  139. #endif
  140.  
  141. /*
  142. **      Duplicate a string.
  143. **/
  144. STATIC UBYTE *DupStr( AD *ad, UBYTE *str )
  145. {
  146.         UBYTE                   *dup = AllocMemory( strlen( str ) + 1 );
  147.  
  148.         if ( dup )
  149.                 strcpy( dup, str );
  150.  
  151.         return( dup );
  152. }
  153.  
  154. /*
  155. **      Reply a rexx command.
  156. **/
  157. STATIC VOID ReplyRexxCommand( struct RexxMsg *rxm, LONG prim, LONG sec, UBYTE *res )
  158. {
  159.         UBYTE           buf[ 16 ];
  160.  
  161.         /*
  162.         **      Result wanted?
  163.         **/
  164.         if ( rxm->rm_Action & RXFF_RESULT ) {
  165.                 /*
  166.                 **      Primary result?
  167.                 **/
  168.                 if ( ! prim ) {
  169.                         /*
  170.                         **      We setup the secondary result to
  171.                         **      the result string when one was passed.
  172.                         **/
  173.                         sec = res ? ( LONG )CreateArgstring( res, strlen( res )) : 0L;
  174.                 } else {
  175.                         /*
  176.                         **      Primary result bigger than 0?
  177.                         **/
  178.                         if ( prim > 0 ) {
  179.                                 /*
  180.                                 **      Setup the result field
  181.                                 **      to point to a string containing
  182.                                 **      the secondary result number.
  183.                                 **/
  184.                                 sprintf( buf, "%ld", sec );
  185.                                 res = buf;
  186.                         } else {
  187.                                 /*
  188.                                 **      Negate primary result and
  189.                                 **      setup the result field to
  190.                                 **      the secondary result.
  191.                                 **/
  192.                                 prim = -prim;
  193.                                 res = ( UBYTE * )sec;
  194.                         }
  195.  
  196.                         /*
  197.                         **      Setup ARexx it's "RC2" variable to
  198.                         **      the result.
  199.                         **/
  200.                         SetRexxVar(( struct Message * )rxm, "RC2", res, strlen( res ));
  201.  
  202.                         /*
  203.                         **      Clear secondary result.
  204.                         **/
  205.                         sec = 0L;
  206.                 }
  207.         } else if ( prim < 0 )
  208.                 /*
  209.                 **      Negate primary result.
  210.                 **/
  211.                 prim = -prim;
  212.  
  213.         /*
  214.         **      Setup result fields.
  215.         **/
  216.         rxm->rm_Result1 = prim;
  217.         rxm->rm_Result2 = sec;
  218.  
  219.         /*
  220.         **      Reply the RexxMsg.
  221.         **/
  222.         ReplyMsg(( struct Message * )rxm );
  223. }
  224.  
  225. /*
  226. **      Free a RexxMsg command.
  227. **/
  228. STATIC VOID FreeRexxCommand( struct RexxMsg *rxm )
  229. {
  230.         /*
  231.         **      Delete the result Argstring.
  232.         **/
  233.         if ( ! rxm->rm_Result1 && rxm->rm_Result2 )
  234.                 DeleteArgstring(( UBYTE * )rxm->rm_Result2 );
  235.  
  236.         /*
  237.         **      Close input handle.
  238.         **/
  239.         if ( rxm->rm_Stdin && rxm->rm_Stdin != Input()) {
  240.                 /*
  241.                 **      If the output handle is the
  242.                 **      same as the input handle we
  243.                 **      can safely clear it.
  244.                 **/
  245.                 if ( rxm->rm_Stdout == rxm->rm_Stdin )
  246.                         rxm->rm_Stdout = NULL;
  247.                 Close( rxm->rm_Stdin );
  248.                 rxm->rm_Stdin = NULL;
  249.         }
  250.  
  251.         /*
  252.         **      Close output handle if it is not
  253.         **      the same as Stdin.
  254.         **/
  255.         if ( rxm->rm_Stdout && rxm->rm_Stdout != Output()) {
  256.                 Close( rxm->rm_Stdout );
  257.                 rxm->rm_Stdout = NULL;
  258.         }
  259.  
  260.         /*
  261.         **      Delete the command Argstring.
  262.         **/
  263.         DeleteArgstring(( UBYTE * )ARG0( rxm ));
  264.         /*
  265.         **      Delete the message itself.
  266.         **/
  267.         DeleteRexxMsg( rxm );
  268. }
  269.  
  270. /*
  271. **      Create a RexxMsg command.
  272. **/
  273. STATIC struct RexxMsg *CreateRexxCommand( AD *ad, UBYTE *comname, BPTR handle )
  274. {
  275.         struct RexxMsg                  *rxm;
  276.  
  277.         /*
  278.         **      Create the RexxMsg.
  279.         **/
  280.         if ( rxm = CreateRexxMsg( ad->ad_Port, ad->ad_FileExt, ad->ad_HostName )) {
  281.                 /*
  282.                 **      Create the Argstring.
  283.                 **/
  284.                 if ( rxm->rm_Args[ 0 ] = CreateArgstring( comname, strlen( comname ))) {
  285.                         /*
  286.                         **      Setup action flags.
  287.                         **/
  288.                         rxm->rm_Action = RXCOMM | RXFF_RESULT;
  289.                         /*
  290.                         **      Setup file handles.
  291.                         **/
  292.                         rxm->rm_Stdin  = rxm->rm_Stdout = handle;
  293.                         return( rxm );
  294.                 }
  295.                 /*
  296.                 **      Argstring creation failed.
  297.                 **/
  298.                 DeleteRexxMsg( rxm );
  299.         }
  300.         return( NULL );
  301. }
  302.  
  303. /*
  304. **      Send a RexxMsg command to the
  305. **      ARexx server.
  306. **/
  307. STATIC struct RexxMsg *CommandToRexx( AD *ad, struct RexxMsg *rxm )
  308. {
  309.         struct MsgPort          *rxp;
  310.  
  311.         /*
  312.         **      Try to find the "REXX"
  313.         **      message port.
  314.         **/
  315.         Forbid();
  316.  
  317.         if ( ! ( rxp = FindPort( RXSDIR ))) {
  318.                 /*
  319.                 **      Oops. ARexx server
  320.                 **      not active.
  321.                 **/
  322.                 Permit();
  323.                 return( NULL );
  324.         }
  325.  
  326.         /*
  327.         **      Send off the message.
  328.         **/
  329.         PutMsg( rxp, &rxm->rm_Node );
  330.  
  331.         Permit();
  332.  
  333.         /*
  334.         **      Increase pending counter.
  335.         **/
  336.         ad->ad_PendCnt++;
  337.  
  338.         return( rxm );
  339. }
  340.  
  341. /*
  342. **      Send a command to the ARexx server.
  343. **/
  344. STATIC struct RexxMsg *SendRexxCommand( AD *ad, UBYTE *comname, BPTR handle )
  345. {
  346.         struct RexxMsg                  *rxm;
  347.  
  348.         /*
  349.         **      Create a RexxMsg command and
  350.         **      send it off to the ARexx server.
  351.         **/
  352.         if ( rxm = CreateRexxCommand( ad, comname, handle ))
  353.                 return( CommandToRexx( ad, rxm ));
  354.  
  355.         return( NULL );
  356. }
  357.  
  358. STATIC REXXCOMMAND *FindRXCommand( AD *ad, UBYTE *comname, UWORD len )
  359. {
  360.         REXXCOMMAND             *rc = ad->ad_Commands;
  361.  
  362.         while ( rc->rc_Func ) {
  363.                 if ( ! strnicmp( comname, rc->rc_Name, len ) && isspace( comname[ strlen( rc->rc_Name ) ] ))
  364.                         return( rc );
  365.                 rc++;
  366.         }
  367.  
  368.         return( NULL );
  369. }
  370.  
  371. /*
  372. **      Execute a command.
  373. **/
  374. STATIC VOID DoRXCommand( AD *ad, struct RexxMsg *rxm )
  375. {
  376.         struct RexxMsg                  *rm;
  377.         REXXCOMMAND                     *rco;
  378.         REXXARGS                        *ra;
  379.         UBYTE                           *comname, *args, *tmp, *result = NULL;
  380.         LONG                             rc = 20, rc2 = 0;
  381.         UWORD                            numargs = 0, len = 0;
  382.  
  383.         /*
  384.         **      Allocate memory for the command
  385.         **      name and it's argument string.
  386.         **/
  387.         if ( ! ( comname = ( UBYTE * )AllocMemory( strlen(( UBYTE * )ARG0( rxm )) + 2 ))) {
  388.                 rc2 = ERROR_NO_FREE_STORE;
  389.                 return;
  390.         }
  391.  
  392.         /*
  393.         **      Copy command name and argument string.
  394.         **/
  395.         strcpy( comname, ( UBYTE * )ARG0( rxm ));
  396.  
  397.         /*
  398.         **      ReadArgs() requires the argument
  399.         **      string to end with a newline.
  400.         **/
  401.         strcat( comname, "\n" );
  402.  
  403.         /*
  404.         **      Find the length of the command
  405.         **      the start of the arguments.
  406.         **/
  407.         args = comname;
  408.         while ( isspace( *args )) args++;
  409.         tmp  = args;
  410.         while ( ! isspace( *args )) { len++; args++; }
  411.  
  412.         /*
  413.         **      Find the command.
  414.         **/
  415.         if ( rco = FindRXCommand( ad, tmp, len )) {
  416.                 /*
  417.                 **      Allocate REXXARGS structure.
  418.                 **/
  419.                 if ( ra = ( REXXARGS * )AllocMemory( sizeof( REXXARGS ))) {
  420.                         /*
  421.                         **      Count number of expected args.
  422.                         **/
  423.                         if ( rco->rc_ArgTemplate ) {
  424.                                 tmp = rco->rc_ArgTemplate;
  425.                                 while ( *tmp != '\n' ) {
  426.                                         if ( *tmp++ == ',' ) numargs++;
  427.                                 }
  428.                                 numargs++;
  429.                                 /*
  430.                                 **      Allocate arg array.
  431.                                 **/
  432.                                 if ( ra->ra_ArgList = ( ULONG * )AllocMemory( numargs * sizeof( ULONG ))) {
  433.                                         /*
  434.                                         **      Setup RDArgs.
  435.                                         **/
  436.                                         ad->ad_DOSParser->RDA_Source.CS_Buffer = args;
  437.                                         ad->ad_DOSParser->RDA_Source.CS_Length = strlen( args );
  438.                                         ad->ad_DOSParser->RDA_Source.CS_CurChr = 0;
  439.                                         ad->ad_DOSParser->RDA_DAList           = NULL;
  440.                                         ad->ad_DOSParser->RDA_Buffer           = NULL;
  441.                                         /*
  442.                                         **      Parse args.
  443.                                         **/
  444.                                         if ( ReadArgs( rco->rc_ArgTemplate, ra->ra_ArgList, ad->ad_DOSParser )) {
  445.                                                 /*
  446.                                                 **      Call the REXX routine.
  447.                                                 **/
  448.                                                 ( rco->rc_Func )( ra, rxm );
  449.  
  450.                                                 rc     = ra->ra_RC;
  451.                                                 rc2    = ra->ra_RC2;
  452.                                                 result = ra->ra_Result;
  453.  
  454.                                                 FreeArgs( ad->ad_DOSParser );
  455.                                         } else {
  456.                                                 rc = 10;
  457.                                                 rc2 = IoErr();
  458.                                         }
  459.                                         FreeMemory( ra->ra_ArgList );
  460.                                 } else
  461.                                         rc2 = ERROR_NO_FREE_STORE;
  462.                         } else {
  463.                                 /*
  464.                                 **      No args.
  465.                                 **/
  466.                                 ( rco->rc_Func )( ra, rxm );
  467.  
  468.                                 rc     = ra->ra_RC;
  469.                                 rc2    = ra->ra_RC2;
  470.                                 result = ra->ra_Result;
  471.                         }
  472.                         FreeMemory( ra );
  473.                 } else
  474.                         rc2 = ERROR_NO_FREE_STORE;
  475.         } else {
  476.                 /*
  477.                 **      Not found in our list?
  478.                 **      Maybe it's a script.
  479.                 **/
  480.                 if ( rm = CreateRexxCommand( ad, ( UBYTE * )ARG0( rxm ), NULL )) {
  481.                         /*
  482.                         **      Save original message.
  483.                         **/
  484.                         rm->rm_Args[ 15 ] = ( STRPTR )rxm;
  485.                         /*
  486.                         **      Let the REXX server see what
  487.                         **      it can do with this.
  488.                         **/
  489.                         if ( ! CommandToRexx( ad, rm ))
  490.                                 rc2 = ERROR_NOT_IMPLEMENTED;
  491.                 } else
  492.                         rc2 = ERROR_NO_FREE_STORE;
  493.  
  494.                 goto byeBye;
  495.         }
  496.  
  497.         ReplyRexxCommand( rxm, rc, rc2, result );
  498.  
  499.         byeBye:
  500.  
  501.         FreeMemory( comname );
  502. }
  503.  
  504. /*
  505. **      OM_NEW.
  506. **/
  507. STATIC ULONG ARexxNew( Class *cl, Object *obj, struct opSet *ops )
  508. {
  509.         struct TagItem         *attr = ops->ops_AttrList, *tag;
  510.         struct MsgPort         *mp;
  511.         AD                     *ad;
  512.         ULONG                   rc, *ecode, ext = 1L;
  513.         UBYTE                   unique_name[ 80 ], *tmp;
  514.  
  515.         /*
  516.         **      Let the superclass set us up...
  517.         **/
  518.         if ( rc = ( ULONG )DoSuperMethodA( cl, obj, ( Msg )ops )) {
  519.                 /*
  520.                 **      Get the instance data.
  521.                 **/
  522.                 ad = ( AD * )INST_DATA( cl, rc );
  523.                 /*
  524.                 **      Safety precautions.
  525.                 **/
  526.                 bzero(( char * )ad, sizeof( AD ));
  527.  
  528.                 /*
  529.                 **      First see if we got error storage.
  530.                 **/
  531.                 if ( tag = FindTagItem( AC_ErrorCode, attr ))
  532.                         ecode = ( ULONG * )tag->ti_Data;
  533.  
  534. #ifdef POOLS
  535.                 /*
  536.                 **      Create a memory pool.
  537.                 **/
  538.                 if ( ad->ad_MemPool = LibCreatePool( MEMF_PUBLIC | MEMF_CLEAR, 4096L, 4096L )) {
  539. #endif
  540.                 /*
  541.                 **      Create port if a
  542.                 **      host name is supplied.
  543.                 **/
  544.                 if ( tag = FindTagItem( AC_HostName, attr )) {
  545.                         /*
  546.                         **      Store host name.
  547.                         **/
  548.                         ad->ad_HostName = ( UBYTE * )tag->ti_Data;
  549.                         /*
  550.                         **      Name valid?
  551.                         **/
  552.                         if ( ad->ad_HostName && *ad->ad_HostName ) {
  553.                                 /*
  554.                                 **      Make the name unique.
  555.                                 **/
  556.                                 sprintf( unique_name, "%s.1", ad->ad_HostName );
  557.                                 Forbid();
  558.                                 while (( mp = FindPort( unique_name )) && ext <= 99 )
  559.                                         sprintf( unique_name, "%s.%ld", ad->ad_HostName, ++ext );
  560.                                 Permit();
  561.                                 /*
  562.                                 **      Name unique?
  563.                                 **/
  564.                                 if ( ! mp ) {
  565.                                         /*
  566.                                         **      Copy the name.
  567.                                         **/
  568.                                         if ( ad->ad_HostName = DupStr( ad, unique_name )) {
  569.                                                 /*
  570.                                                 **      Uppercase it.
  571.                                                 **/
  572.                                                 tmp = ad->ad_HostName;
  573.                                                 while ( *tmp ) {
  574.                                                         *tmp = toupper( *tmp );
  575.                                                         tmp++;
  576.                                                 }
  577.                                                 /*
  578.                                                 **      Create the port.
  579.                                                 **/
  580.                                                 if ( ad->ad_Port = CreateMsgPort()) {
  581.                                                         /*
  582.                                                         **      Initialize and add the port.
  583.                                                         **/
  584.                                                         ad->ad_Port->mp_Node.ln_Name = ad->ad_HostName;
  585.                                                         ad->ad_Port->mp_Node.ln_Pri  = 0;
  586.                                                         AddPort( ad->ad_Port );
  587.                                                 } else if ( ecode )
  588.                                                         *ecode = RXERR_OUT_OF_MEMORY;
  589.                                         } else if ( ecode )
  590.                                                 *ecode = RXERR_OUT_OF_MEMORY;
  591.                                 } else if ( ecode )
  592.                                         *ecode = RXERR_PORT_ALREADY_EXISTS;
  593.                         } else if ( ecode )
  594.                                 *ecode = RXERR_NO_PORT_NAME;
  595.                 } else if ( ecode )
  596.                         *ecode = RXERR_NO_PORT_NAME;
  597.  
  598.                 /*
  599.                 **      Do we have a port now?
  600.                 **/
  601.                 if ( ad->ad_Port ) {
  602.                         /*
  603.                         **      Find the commandlist.
  604.                         **/
  605.                         if ( tag = FindTagItem( AC_CommandList, attr )) {
  606.                                 if ( ad->ad_Commands = ( REXXCOMMAND * )tag->ti_Data ) {
  607.                                         /*
  608.                                         **      Setup the AmigaDOS parser.
  609.                                         **/
  610.                                         if ( ad->ad_DOSParser = ( struct RDArgs * )AllocDosObject( DOS_RDARGS, NULL )) {
  611.                                                 ad->ad_DOSParser->RDA_Flags = RDAF_NOPROMPT;
  612.                                                 /*
  613.                                                 **      Obtain file extention.
  614.                                                 **/
  615.                                                 if ( tag = FindTagItem( AC_FileExtention, attr ))
  616.                                                         ad->ad_FileExt = ( UBYTE * )tag->ti_Data;
  617.                                                 else
  618.                                                         ad->ad_FileExt = "rexx";
  619.                                                 return( rc );
  620.                                         } else if ( ecode )
  621.                                                 *ecode = RXERR_OUT_OF_MEMORY;
  622.                                 } else if ( ecode )
  623.                                         *ecode = RXERR_NO_COMMAND_LIST;
  624.                         } else if ( ecode )
  625.                                 *ecode = RXERR_NO_COMMAND_LIST;
  626.                 }
  627. #ifdef POOLS
  628.                 } else if ( ecode )
  629.                         *ecode = RXERR_OUT_OF_MEMORY;
  630. #endif
  631.                 /*
  632.                 **      Bliep error...bliep....
  633.                 **/
  634.                 CoerceMethod( cl, ( Object * )rc, OM_DISPOSE );
  635.         }
  636.         return( 0L );
  637. }
  638.  
  639. /*
  640. **      OM_DISPOSE.
  641. **/
  642. STATIC ULONG ARexxDispose( Class *cl, Object *obj, Msg msg )
  643. {
  644.         AD                      *ad = ( AD * )INST_DATA( cl, obj );
  645.         struct RexxMsg          *rxm;
  646.  
  647.         /*
  648.         **      Do we have a port?
  649.         **/
  650.         if ( ad->ad_Port ) {
  651.                 /*
  652.                 **      Remove the port from the public list
  653.                 **/
  654.                 RemPort( ad->ad_Port );
  655.                 /*
  656.                 **      Wait for and handle all
  657.                 **      messages still pending.
  658.                 **/
  659.                 if ( ad->ad_PendCnt ) {
  660.                         while ( ad->ad_PendCnt ) {
  661.                                 /*
  662.                                 **      Wait for a message.
  663.                                 **/
  664.                                 WaitPort( ad->ad_Port );
  665.                                 /*
  666.                                 **      Get messages.
  667.                                 **/
  668.                                 while ( rxm = ( struct RexxMsg * )GetMsg( ad->ad_Port )) {
  669.                                         /*
  670.                                         **      Replyed message?
  671.                                         **/
  672.                                         if ( rxm->rm_Node.mn_Node.ln_Type == NT_REPLYMSG ) {
  673.                                                 /*
  674.                                                 **      Free the message and decrease the
  675.                                                 **      pending counter.
  676.                                                 **/
  677.                                                 FreeRexxCommand( rxm );
  678.                                                 ad->ad_PendCnt--;
  679.                                         } else
  680.                                                 /*
  681.                                                 **      Tell'm where getting out of here.
  682.                                                 **/
  683.                                                 ReplyRexxCommand( rxm, -20, ( LONG )"Host object closing down", NULL );
  684.                                 }
  685.                         }
  686.                 } else {
  687.                         /*
  688.                         **      In case there are no messages pending we
  689.                         **      still need to reply all that is waiting at
  690.                         **      the port.
  691.                         **/
  692.                         while ( rxm = ( struct RexxMsg * )GetMsg( ad->ad_Port ))
  693.                                 ReplyRexxCommand( rxm, -20, ( LONG )"Host object closing down", NULL );
  694.                 }
  695.  
  696.                 /*
  697.                 **      Delete the port.
  698.                 **/
  699.                 DeleteMsgPort( ad->ad_Port );
  700.         }
  701.  
  702.         /*
  703.         **      Delete the AmigaDOS parser.
  704.         **/
  705.         if ( ad->ad_DOSParser )
  706.                 FreeDosObject( DOS_RDARGS, ad->ad_DOSParser );
  707.  
  708.         /*
  709.         **      Delete the port name.
  710.         **/
  711.         if ( ad->ad_HostName )
  712.                 FreeMemory( ad->ad_HostName );
  713.  
  714. #ifdef POOLS
  715.         /*
  716.         **      Free the pool.
  717.         **/
  718.         LibDeletePool( ad->ad_MemPool );
  719. #endif
  720.  
  721.         /*
  722.         **      Let the superclass do the rest.
  723.         **/
  724.         return( DoSuperMethodA( cl, obj, msg ));
  725. }
  726.  
  727. /*
  728. **      ACM_EXECUTE.
  729. **/
  730. STATIC ULONG ARexxExecute( Class *cl, Object *obj, struct acmExecute *acme )
  731. {
  732.         AD                              *ad = ( AD * )INST_DATA( cl, obj );
  733.         REXXCOMMAND                     *rco;
  734.         REXXARGS                        *ra;
  735.         struct RexxMsg                  *rxm;
  736.         UBYTE                           *args, *tmp, *result = NULL, *com;
  737.         UWORD                            numargs = 0, len = 0;
  738.         ULONG                            r = 20, r2;
  739.  
  740.         /*
  741.         **      Allocate a private copy of the command string.
  742.         **/
  743.         if ( com = ( UBYTE * )AllocMemory( strlen( acme->acme_CommandString ) + 2 )) {
  744.                 /*
  745.                 **      Make a copy terminated with a newline.
  746.                 **/
  747.                 strcpy( com, acme->acme_CommandString );
  748.                 strcat( com, "\n" );
  749.                 /*
  750.                 **      Find the length of the command
  751.                 **      and the start of the arguments.
  752.                 **/
  753.                 args = com;
  754.                 while ( isspace( *args ))   args++;
  755.                 tmp = args;
  756.                 while ( ! isspace( *args )) { len++; args++; }
  757.                 /*
  758.                 **      Look up the command.
  759.                 **/
  760.                 if ( rco = FindRXCommand( ad, tmp, len )) {
  761.                         /*
  762.                         **      Allocate a REXXARGS structure.
  763.                         **/
  764.                         if ( ra = ( REXXARGS * )AllocMemory( sizeof( REXXARGS ))) {
  765.                                 /*
  766.                                 **      Args expected?
  767.                                 **/
  768.                                 if ( rco->rc_ArgTemplate ) {
  769.                                         /*
  770.                                         **      Count the expected number of arguments.
  771.                                         **/
  772.                                         tmp = rco->rc_ArgTemplate;
  773.                                         while ( *tmp != '\n' ) {
  774.                                                 if ( *tmp++ != ',' ) numargs++;
  775.                                         }
  776.                                         numargs++;
  777.                                         /*
  778.                                         **      Allocate space to parse the args.
  779.                                         **/
  780.                                         if ( ra->ra_ArgList = ( ULONG * )AllocMemory( numargs * sizeof( ULONG ))) {
  781.                                                 /*
  782.                                                 **      Setup the parser.
  783.                                                 **/
  784.                                                 ad->ad_DOSParser->RDA_Source.CS_Buffer = args;
  785.                                                 ad->ad_DOSParser->RDA_Source.CS_Length = strlen( args );
  786.                                                 ad->ad_DOSParser->RDA_Source.CS_CurChr = 0;
  787.                                                 ad->ad_DOSParser->RDA_DAList           = NULL;
  788.                                                 ad->ad_DOSParser->RDA_Buffer           = NULL;
  789.                                                 /*
  790.                                                 **      Parse the args.
  791.                                                 **/
  792.                                                 if ( ReadArgs( rco->rc_ArgTemplate, ra->ra_ArgList, ad->ad_DOSParser )) {
  793.                                                         /*
  794.                                                         **      Run command.
  795.                                                         **/
  796.                                                         ( rco->rc_Func )( ra, NULL );
  797.                                                         /*
  798.                                                         **      Store results.
  799.                                                         **/
  800.                                                         r      = ra->ra_RC;
  801.                                                         r2     = ra->ra_RC2;
  802.                                                         result = ra->ra_Result;
  803.                                                         FreeArgs( ad->ad_DOSParser );
  804.                                                 } else {
  805.                                                         r  = 10;
  806.                                                         r2 = IoErr();
  807.                                                 }
  808.                                                 /*
  809.                                                 **      Deallocate arg list.
  810.                                                 **/
  811.                                                 FreeMemory( ra->ra_ArgList );
  812.                                         } else
  813.                                                 r2 = ERROR_NO_FREE_STORE;
  814.                                 } else {
  815.                                         /*
  816.                                         **      Run command.
  817.                                         **/
  818.                                         ( rco->rc_Func )( ra, NULL );
  819.                                         /*
  820.                                         **      Store results.
  821.                                         **/
  822.                                         r      = ra->ra_RC;
  823.                                         r2     = ra->ra_RC2;
  824.                                         result = ra->ra_Result;
  825.                                 }
  826.                                 /*
  827.                                 **      Deallocate the REXXARGS structure.
  828.                                 **/
  829.                                 FreeMemory( ra );
  830.                         } else
  831.                                 r2 = ERROR_NO_FREE_STORE;
  832.                         /*
  833.                         **      When not passed to the rexx server
  834.                         **      we must close the given IO handle
  835.                         **      ourselves.
  836.                         **/
  837.                         if ( acme->acme_IO ) Close( acme->acme_IO );
  838.                 } else {
  839.                         /*
  840.                         **      We do not send the new-line to
  841.                         **      the ARexx server.
  842.                         **/
  843.                         com[ strlen( com ) - 1 ] = '\0';
  844.                         /*
  845.                         **      Unknown commands are shipped
  846.                         **      off to the REXX server.
  847.                         **/
  848.                         if ( rxm = CreateRexxCommand( ad, com, acme->acme_IO )) {
  849.                                 if ( ! CommandToRexx( ad, rxm ))
  850.                                         r2 = ERROR_NOT_IMPLEMENTED;
  851.                                 else
  852.                                         r = r2 = 0L;
  853.                         } else
  854.                                 r2 = ERROR_NO_FREE_STORE;
  855.                 }
  856.                 /*
  857.                 **      Deallocate the command copy.
  858.                 **/
  859.                 FreeMemory( com );
  860.         } else
  861.                 r2 = ERROR_NO_FREE_STORE;
  862.  
  863.         /*
  864.         **      Put the results into their
  865.         **      storage spaces.
  866.         **/
  867.         if ( acme->acme_RC     ) *( acme->acme_RC     ) = r;
  868.         if ( acme->acme_RC2    ) *( acme->acme_RC2    ) = r2;
  869.         if ( acme->acme_Result ) *( acme->acme_Result ) = result;
  870.  
  871.         return( 1L );
  872. }
  873.  
  874. /*
  875. **      OM_GET.
  876. **/
  877. STATIC ULONG ARexxGet( Class *cl, Object *obj, struct opGet *opg )
  878. {
  879.         AD                      *ad = ( AD * )INST_DATA( cl, obj );
  880.         ULONG                   rc = 1L;
  881.  
  882.         /*
  883.         **      What do they want?
  884.         **/
  885.         switch ( opg->opg_AttrID ) {
  886.  
  887.                 case    AC_HostName:
  888.                         *( opg->opg_Storage ) = ( ULONG )ad->ad_HostName;
  889.                         break;
  890.  
  891.                 case    AC_RexxPortMask:
  892.                         *( opg->opg_Storage ) |= ( 1L << ad->ad_Port->mp_SigBit );
  893.                         break;
  894.  
  895.                 default:
  896.                         rc = DoSuperMethodA( cl, obj, ( Msg )opg );
  897.                         break;
  898.         }
  899.         return( rc );
  900. }
  901.  
  902. /*
  903. **      ACM_HANDLE_EVENT.
  904. **/
  905. STATIC ULONG ARexxHandleEvent( Class *cl, Object *obj, Msg msg )
  906. {
  907.         struct RexxMsg          *rxm, *org;
  908.         AD                      *ad = ( AD * )INST_DATA( cl, obj );
  909.         ULONG                    rc = 1L;
  910.  
  911.         /*
  912.         **      Get the messages from the port.
  913.         **/
  914.         while ( rxm = ( struct RexxMsg * )GetMsg( ad->ad_Port )) {
  915.                 /*
  916.                 **      A Rexx command?
  917.                 **/
  918.                 if (( rxm->rm_Action & RXCODEMASK ) != RXCOMM )
  919.                         ReplyMsg(( struct Message * )rxm );
  920.                 else if ( rxm->rm_Node.mn_Node.ln_Type == NT_REPLYMSG ) {
  921.                         /*
  922.                         **      Reply'd message. See if it was started
  923.                         **      as a script.
  924.                         **/
  925.                         if ( org = ( struct RexxMsg * )rxm->rm_Args[ 15 ] ) {
  926.                                 if ( rxm->rm_Result1 )
  927.                                         ReplyRexxCommand( org, 20, ERROR_NOT_IMPLEMENTED, NULL );
  928.                                 else
  929.                                         ReplyRexxCommand( org, 0, 0, ( UBYTE * )rxm->rm_Result2 );
  930.                         }
  931.                         /*
  932.                         **      Free the message and decrease the
  933.                         **      pending counter.
  934.                         **/
  935.                         FreeRexxCommand( rxm );
  936.                         ad->ad_PendCnt--;
  937.                 } else if ( ARG0( rxm ))
  938.                         /*
  939.                         **      Execute message.
  940.                         **/
  941.                         DoRXCommand( ad, rxm );
  942.                 else
  943.                         ReplyMsg(( struct Message * )rxm );
  944.         }
  945. }
  946.  
  947. /*
  948. **      Class dispatcher.
  949. **/
  950. STATIC SAVEDS ASM ULONG ARexxDispatch( REG(A0) Class *cl, REG(A2) Object *obj, REG(A1) Msg msg )
  951. {
  952.         ULONG                   rc = 0L;
  953.  
  954.         /*
  955.         **      Evaluate the method.
  956.         **/
  957.         switch ( msg->MethodID ) {
  958.  
  959.                 case    OM_NEW:
  960.                         rc = ARexxNew( cl, obj, ( struct opSet * )msg );
  961.                         break;
  962.  
  963.                 case    OM_GET:
  964.                         rc = ARexxGet( cl, obj, ( struct opGet * )msg );
  965.                         break;
  966.  
  967.                 case    OM_DISPOSE:
  968.                         rc = ARexxDispose( cl, obj, msg );
  969.                         break;
  970.  
  971.                 case    ACM_HANDLE_EVENT:
  972.                         rc = ARexxHandleEvent( cl, obj, msg );
  973.                         break;
  974.  
  975.                 case    ACM_EXECUTE:
  976.                         rc = ARexxExecute( cl, obj, ( struct acmExecute * )msg );
  977.                         break;
  978.  
  979.                 default:
  980.                         rc = DoSuperMethodA( cl, obj, msg );
  981.                         break;
  982.         }
  983.         return ( rc );
  984. }
  985.